package com.sleepcamel.rest.domain;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class JavaClass implements IImportDependant {

	public static final JavaClass voidClass = new JavaClass("void");
	
	private String name;
	private String packageName;
	private boolean primitive;
	private JavaProperty id;
    private List<? extends JavaProperty> properties;
    private List<JavaClass> genericTypes;

    protected JavaClass() {}
    
	public JavaClass(String name) {
		properties = new ArrayList<JavaProperty>();
		this.name = name;
		primitive = true;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPackageName() {
		return packageName;
	}

	public void setPackageName(String packageName) {
		this.packageName = packageName;
	}

	public boolean isPrimitive() {
		return primitive;
	}

	public void setPrimitive(boolean primitive) {
		this.primitive = primitive;
	}

	public JavaProperty getId() {
		return id;
	}

	public void setId(JavaProperty id) {
		this.id = id;
	}

	public String getCanonicalName() {
		if ( packageName == null )
			return name;

		return packageName + "." + name;
	}

	public List<? extends JavaProperty> getProperties() {
		return properties;
	}

	public void setProperties(List<? extends JavaProperty> properties) {
		this.properties = properties;
	}

	public boolean isArray() {
		// TODO Auto-generated method stub
		return false;
	}

	// Returns type of array. For example, Person[] returns Person
	public JavaClass getComponentType() {
		// TODO Auto-generated method stub
		return null;
	}

	public List<JavaClass> getGenericTypes() {
		return genericTypes;
	}

	public void setGenericTypes(List<JavaClass> genericTypes) {
		this.genericTypes = genericTypes;
	}

	@Override
	public Set<String> getClassImports() {
		HashSet<String> hashSet = new HashSet<String>();
		if ( !isPrimitive() ){
			if ( isArray() ){
				hashSet.addAll(getComponentType().getClassImports());
			}else{
				hashSet.add(getCanonicalName());
				if( genericTypes != null ){
					for(JavaClass clazz:genericTypes){
						hashSet.addAll(clazz.getClassImports());
					}
				}
			}
		}
		return hashSet;
	}

	@Override
	public Set<String> getInterfaceImports() {
		return getClassImports();
	}

	public List<? extends JavaProperty> getAllProperties() {
		return properties;
	}

	public JavaClass asList(){
		JavaClass list = new JavaClass("List");
		list.setPackageName("java.util");
		list.setPrimitive(false);
		list.setGenericTypes(Arrays.asList(this));
		return list;
	}
	
	public JavaClass asSet(){
		JavaClass set = new JavaClass("Set");
		set.setPackageName("java.util");
		set.setPrimitive(false);
		set.setGenericTypes(Arrays.asList(this));
		return set;
	}
	
	public JavaProperty getPropertyByName(String propertyName){
		for(JavaProperty property:getAllProperties()){
			if ( property.getName().equals(propertyName) )
				return property;
		}
		return null;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		JavaClass other = (JavaClass) obj;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	
	@Override
	public String toString() {
		return getCanonicalName(); 
	}
}
